<template>
  <div class="canvas-page">
    <div class="topDiv" v-if="option.legendPosition === 'top'" :style="{'font-size': `${option.legFontSize}px`}">
      <div class="legend" style="margin-right: 26px;" v-for="(item,i) of option.legends" :key="i">
        <div :style="{ background: colors[i] }"
          class="tuli"></div>
        <div>{{ item }}</div>
      </div>
    </div>
    <div :style="{height: option.canvasH}" :id="barChartsId" class="barCharts">
      <canvas :id="chartId" :width="cw" :height="ch" v-if="showCanvas" @mousemove="mouseover" @mouseleave="mouseleave">
      </canvas>
    </div>
    <div class="bottomDiv" :style="{'font-size': `${option.xAxis[0].fontSize}px`, 'padding-left': `${option.basePointX}px`}">
      <div v-for="(item, i) of option.xAxis[0].data" :key="i" :style="{ 'width': xInterval + 'px' }">{{ item }}</div>
    </div>
    <div class="topDiv" v-if="option.legendPosition === 'bottom'" :style="{'font-size': `${option.legFontSize}px`}">
      <div class="legend" style="margin-right: 26px;" v-for="(item,i) of option.legends" :key="i">
        <div :style="{ background: colors[i] }"
          class="tuli"></div>
        <div>{{ item }}</div>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    chartId: {
      type: String,
      default: ""
    },
    barChartsId: {
      type: String,
      default: ""
    },
    option: {
      type: Object,
      default: () => {}
    }
  },
  data() {
    return {
      cw: 0,
      ch: 0,
      colors: [],
      colorList: [
        { color1: "rgba(192, 132, 89, 0.9)", color2: "rgba(225, 196, 139, 0.9)" },
        { color1: "rgba(34, 188, 70, 0.9)", color2: "rgba(111, 240, 147, 0.9)" },
        { color1: "rgba(11, 97, 176, 0.9)", color2: "rgba(97, 151, 232, 0.9)" },
        { color1: "rgba(45, 141, 183, 0.9)", color2: "rgba(139, 194, 225, 0.9)" },
        { color1: "rgba(66, 189, 108, 0.9)", color2: "rgba(139, 225, 168, 0.9)" }
      ],
      showCanvas: false,
      xInterval: 0, // x轴间隔
      yMax: 0,
      tooltipArr: [],
      baseX: 0,
      yHeight: 0, // Y轴高度
      barWidth: 70, // 柱子宽度
      basePointX: 50,
      offsetHeight: 10, // 顶部和底部菱形突出的高度
      yNum: 5 // Y轴分数
    };
  },
  created() {
    this.option.legends.forEach((el, i) => {
      this.colors[i] = "linear-gradient(90deg," + this.colorList[i].color1 + "," + this.colorList[i].color2 + ")";
    });
    this.barWidth = this.option.barWidth;
    this.basePointX = this.option.basePointX;
    this.offsetHeight = this.option.offsetHeight;
    this.yNum = this.option.yNum;
  },
  mounted() {
    const barCharts = document.querySelector(`#${this.barChartsId}`);
    this.cw = barCharts.offsetWidth;
    this.ch = barCharts.offsetHeight;
    this.showCanvas = true;
    this.$nextTick(() => {
      this.getBaseData(this.cw, this.ch);
      this.option.series.forEach((el, i) => {
        this.getData(el, i);
      });
    });
  },
  methods: {
    mouseleave() {
      const canvas = document.getElementById(`${this.barChartsId}`);
      const child = document.getElementById("weiyid");
      if (child) canvas.removeChild(child);
    },
    // 获取基本数据
    getBaseData(cw, ch) {
      const basePointX = this.basePointX;
      // 原点离底部的距离
      const basePointY = ch - 16;
      // 距离右边的距离
      const xEndX = cw - this.option.grid.right;
      // x轴长度
      const xLength = xEndX - basePointX;
      const xInterval = xLength / this.option.xAxis[0].data.length;
      this.xInterval = xInterval;
      this.baseX = Math.floor(xInterval) / 2 - (this.barWidth / 2) + basePointX;
      const xEndY = basePointY;
      const yEndX = basePointX;
      const yEndY = basePointY - ch + 80;
      const canvas = document.getElementById(`${this.chartId}`);
      const ctx = canvas.getContext("2d");
      // 坐标轴
      ctx.beginPath();
      ctx.strokeStyle = "#fff";
      ctx.lineWidth = 1;
      ctx.moveTo(yEndX, yEndY);
      ctx.lineTo(basePointX, basePointY);
      ctx.lineTo(xEndX, xEndY);
      ctx.stroke();
      ctx.closePath();
      // 与X轴平行的虚线
      const series = this.option.series;
      const dataArr = [];
      series.forEach(el => {
        dataArr.push(...el);
      });
      // 计算份数
      const max = Math.max(...dataArr);
      const yNum = this.yNum;
      const qyNum = this.option.qyNum;
      const surplus = max % qyNum;
      const myfNum = (max + (qyNum - surplus)) / yNum;
      this.yMax = (max + (qyNum - surplus));
      const yHeight = basePointY - yEndY;
      this.yHeight = yHeight;
      const yInterval = yHeight / yNum;
      const arr = [];
      const ytps = [];
      // Y轴左侧数字
      for (let i = 1; i <= yNum; i++) {
        ytps.push({ x: basePointX, y: basePointY - (yInterval * i - 5) });
        arr.push([{ x: basePointX, y: basePointY - (yInterval * i) }, { x: xEndX, y: basePointY - (yInterval * i) }]);
      }
      // y轴顶部名称的位置
      const item = JSON.parse(JSON.stringify(ytps.slice(-1)[0]));
      item.y -= 28;
      ytps.unshift({ x: basePointX, y: basePointY - (yInterval * 0 - 5) });
      arr.forEach(el => {
        const canvas = document.getElementById(`${this.chartId}`);
        const ctx = canvas.getContext("2d");
        ctx.beginPath();
        // 坐标轴
        ctx.strokeStyle = "#aaa";
        ctx.lineWidth = 1;
        ctx.moveTo(el[0].x, el[0].y);
        ctx.lineTo(el[1].x, el[1].y);
        ctx.setLineDash([5, 5]);
        ctx.stroke();
        ctx.closePath();
      });
      ytps.forEach((el, i) => {
        const fontSize = this.option.yAxis.nameTextStyle.fontSize;
        const num = Math.ceil(i * myfNum);
        const numlength = num.toString().length;
        const ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.font = `${fontSize}px sans-serif`;
        ctx.fillStyle = "#fff";
        ctx.fillText(`${num}`, el.x - (36 * numlength * 0.75), el.y);
      });
      // y轴顶部名字
      ctx.beginPath();
      ctx.font = "16px sans-serif";
      ctx.fillStyle = "#fff";
      ctx.fillText(`${this.option.yAxis.name}`, item.x, item.y);
    },
    mouseover(e) {
      for (let i = 0; i < this.tooltipArr.length; i++) {
        const canvas = document.getElementById(`${this.barChartsId}`);
        const child = document.getElementById("weiyid");
        const offsetX = e.offsetX;
        const offsetY = e.offsetY;
        if (child) canvas.removeChild(child);
        const el = this.tooltipArr[i];
        if (offsetX > el.x1 && offsetX < el.x2 && offsetY < el.y1 && offsetY > el.y2) {
          const div = document.createElement("div");
          div.id = "weiyid";
          div.style.position = "absolute";
          let y = offsetY;
          let x = offsetX;
          const { ch1, ch2, ch3 } = this.option.tooltipXandY;
          if (offsetY > this.ch / 2) {
            y = y - ch1;
          } else {
            y = y + ch2;
          }
          if (offsetX > this.cw / 2) {
            x = x - ch3;
          }
          div.style.top = `${y}px`;
          div.style.left = `${x}px`;
          div.style.color = "#fff";
          let htmlStr = "";
          this.option.legends.forEach((el, index) => {
            htmlStr += `<div style="display: flex;align-items: center;padding: 6px;">
              <div style="width: 32px;height: 32px;border-radius: 50%;background: ${this.colorList[index].color1};margin-right: 12px;"></div>
              <div>${el}：${this.option.series[i][index]}${this.option.tooltipdw}</div>
            </div>`;
          });
          div.innerHTML = `
          <div style="background: rgba(255, 255, 255, .2);padding: 6px;font-size: 36px;">
            <div style="padding: 8px;">${this.option.xAxis[0].data[i]}</div>
            ${htmlStr}
          </div>`;
          canvas.appendChild(div);
          return;
        }
      }
    },
    getNextBar(Arr, color1, color2, barHeight = 40) {
      const [a1, a2, a3, a4] = Arr;
      const b1 = { x: a1.x, y: a1.y - barHeight };
      const b2 = { x: a2.x, y: a2.y - barHeight };
      const b3 = { x: a3.x, y: a3.y - barHeight };
      const b4 = { x: a4.x, y: a4.y - barHeight };
      const botArr = [a1, a2, a3, a4];
      // 左侧
      const leftArr = [b1, a1, a2, b2];
      // 右侧
      const rightArr = [b2, a2, a3, b3];
      // 顶部
      const topArr = [b1, b2, b3, b4];
      return [
        { arr: botArr, colors: [color1, color2], barHeight },
        { arr: leftArr, colors: [color1, color2], barHeight },
        { arr: rightArr, colors: [color1.slice(0, -6) + ")", color2.slice(0, -6) + ")"], barHeight },
        { arr: topArr, colors: [color1, color2], barHeight }
      ];
    },
    getData(list, i) {
      // 基数
      const smallJg = this.option.smallJg;
      const barWidth = this.barWidth; // 柱子宽度
      const xInterval = Math.floor(this.xInterval);
      const x1 = (xInterval * i + xInterval / 2) - smallJg / 2 - barWidth + this.basePointX;
      const x2 = (xInterval * i + xInterval / 2) + smallJg / 2 + this.basePointX;
      const y = this.ch - this.option.ylib;
      const offsetHeight = this.offsetHeight; // 顶部和底部菱形突出的高度
      const newArr = [];
      const color1 = this.colorList[0].color1;
      const color2 = this.colorList[0].color2;
      list.forEach((el, j) => {
        const barHeight = el ? Math.ceil(el / this.yMax * this.yHeight) : 0;
        if (j === 0) {
          // 下面 4个点
          const a1 = { x: x1, y };
          const a2 = { x: x1 + barWidth / 2, y: y + offsetHeight };
          const a3 = { x: x1 + barWidth, y: y };
          const a4 = { x: x1 + barWidth / 2, y: y - offsetHeight };
          // 上面 4个点
          const b1 = { x: x1, y: y - barHeight };
          const b2 = { x: x1 + barWidth / 2, y: y + offsetHeight - barHeight };
          const b3 = { x: x1 + barWidth, y: y - barHeight };
          const b4 = { x: x1 + barWidth / 2, y: y - offsetHeight - barHeight };
          // 下边菱形
          const botArr = [a1, a2, a3, a4];
          // 左侧
          const leftArr = [b1, a1, a2, b2];
          // 右侧
          const rightArr = [b2, a2, a3, b3];
          // 顶部
          const topArr = [b1, b2, b3, b4];
          newArr[0] = [
            { arr: botArr, colors: [color1, color2], barHeight },
            { arr: leftArr, colors: [color1, color2], barHeight },
            { arr: rightArr, colors: [color1.slice(0, -6) + ")", color2.slice(0, -6) + ")"], barHeight },
            { arr: topArr, colors: [color1, color2], barHeight }
          ];
        } else {
          const a1 = { x: x2, y };
          const a2 = { x: x2 + barWidth / 2, y: y + offsetHeight };
          const a3 = { x: x2 + barWidth, y: y };
          const a4 = { x: x2 + barWidth / 2, y: y - offsetHeight };
          newArr[j] = this.getNextBar([a1, a2, a3, a4], this.colorList[j].color1, this.colorList[j].color2, Math.ceil(el / this.yMax * this.yHeight));
        }
      });
      const barList = [];
      newArr.forEach(el => {
        if (el[0].barHeight) {
          barList.push(...el);
        }
      });
      this.tooltipArr.push({ x1, x2: newArr[1][0].arr[2].x, y1: y, y2: list[0] > list[1] ? newArr[0][3].arr[0].y : newArr[1][3].arr[0].y });
      this.doMyDraw(barList);
    },
    doMyDraw(newArr) {
      let canvas = document.getElementById(`${this.chartId}`);
      // 由于弹窗，确保已获取到
      const a = setInterval(() => {
        // 重复获取
        canvas = document.getElementById(`${this.chartId}`);
        if (!canvas) {
          return false;
        } else {
          clearInterval(a);
          // 可以理解为一个画笔，可画路径、矩形、文字、图像
          const content = canvas.getContext("2d");
          newArr.forEach((item) => {
            this.draw(item, content);
          });
        }
      }, 1);
    },
    draw(obj, ctx) {
      ctx.beginPath();
      ctx.moveTo(obj.arr[0].x, obj.arr[0].y);
      obj.arr.forEach((item, index) => {
        if (index != 0) {
          ctx.lineTo(obj.arr[index].x, obj.arr[index].y);
        }
      });
      ctx.closePath();
      var gradient = ctx.createLinearGradient(obj.arr[3].x, obj.arr[3].y, obj.arr[0].x, obj.arr[0].y);
      gradient.addColorStop(0, obj.colors[0] || "#8deffe");
      gradient.addColorStop(1, obj.colors[1] || "#3badd7");
      ctx.fillStyle = gradient;
      ctx.fill();
      ctx.strokeStyle = "transparent";
      ctx.lineWidth = 0;
      ctx.stroke();
    },
    clearCanvas(ctx, canvas) {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
    }
  }
};
</script>
<style lang="less" scoped>
.canvas-page {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  .topDiv {
    height: 8%;
    display: flex;
    color: #fff;
    justify-content: center;
    .legend {
      display: flex;
      align-items: center;
      .tuli {
        width: 60px;
        height: 32px;
        border-radius: 5%;
        margin-right: 10px;
      }
    }
  }
  .bottomDiv {
    height: 8%;
    display: flex;
    color: #fff;
    div {
      text-align: center;
      padding: 0 6px;
    }
  }
}
.barCharts {
  display: flex;
  flex-direction: column;
  position: relative;
  canvas {
    cursor: pointer;
  }
}
</style>
